#include "PlayerManager.h"
#include <algorithm>
#include <string>

namespace dgame
{
	PlayerManager::~PlayerManager()
	{
		std::vector<Player *>::iterator i = mPlayers.begin();
		for(; i != mPlayers.end(); ++i)
		{
			delete (*i);
		}
		delete mNextActivePlayer;
	}

	PlayerManager::PlayerManager(const PlayerManager &plm)
	{
		for (int i = 0; i < plm.size(); i++)
		{
			Player *tmp = new Player(plm[i]->getName(), plm[i]->getScore());
			DominoManager dm = plm[i]->getDominoes();
			for (unsigned int j = 0; j < dm.size(); j++)
			{
				tmp->addDomino(dm[j]);
			}
			mPlayers.push_back(tmp);
		}
		mActivePlayer = mPlayers[0];
		mNextActivePlayer = plm.mNextActivePlayer->clone();
	}

	PlayerManager::PlayerManager(ANextPlayer *nextPlayerRule) : 
	mActivePlayer(NULL)
	{
		mNextActivePlayer = nextPlayerRule;
	}


	const Player *PlayerManager::getActivePlayer() const
	{
		return mActivePlayer;
	}

	void PlayerManager::addPlayer(const std::string playerName)
	{
		if (checkPlayer(playerName))
			throw PlayerExistingException();
		mPlayers.push_back(new Player(playerName, 0));
		if (mActivePlayer == NULL)
		{
			mActivePlayer = mPlayers[0];
		}
	}

	void PlayerManager::deletePlayer(const std::string playerName)
	{
		std::vector<Player *>::iterator i = mPlayers.begin();
		for(; i != mPlayers.end(); ++i)
		{
			if ((*i)->getName() == playerName)
				break;
		}

		if(i != mPlayers.end())
		{
			if (mPlayers.size() == 1)
				mActivePlayer = NULL;
			if(*i == mActivePlayer)
				nextPlayer();
			delete (*i);
			mPlayers.erase(i, i + 1);
		}
	}

	bool PlayerManager::checkPlayer(const std::string &playerName) const
	{
		const Player *pl = getPlayer(playerName);
		if (pl != NULL)
			return true;
		else
			return false;
	}

	const Player *PlayerManager::getPlayer(const std::string &playerName)const
	{
		std::vector<Player *>::const_iterator i = mPlayers.begin();
		for(; i != mPlayers.end(); ++i)
		{
			if ((*i)->getName() == playerName)
				return (*i);
		}
		return NULL;
	}

	const Player *PlayerManager::operator [](uint n) const
	{
		try
		{
			return mPlayers.at(n);
		}
		catch(std::out_of_range &ex)
		{
			throw OutOfRangeException
				(std::string("PlayerManager::") + ex.what());
		}
	}

	int PlayerManager::size() const
	{
		return mPlayers.size();
	}

	const Player *PlayerManager::nextPlayer(void *data)
	{
		mActivePlayer = mNextActivePlayer->nextPlayer(&mPlayers[0], mPlayers.size(), mActivePlayer, data);
		return mActivePlayer;
	}
}
